package io.task.cc.network.queue_task;

import io.task.cc.network.ChannelContext;
import io.task.cc.network.maintain.MaintainUtils;
import io.task.cc.network.spi.client.ClientChannelContext;
import io.task.cc.network.spi.client.ClientConfig;
import io.task.cc.network.spi.client.ReconnConf;
import io.task.cc.network.utils.thread.pool.AbstractQueueTask;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;

@Slf4j
@Setter
@Getter
public class CloseQueueTask extends AbstractQueueTask<ChannelContext> {


    public CloseQueueTask(Executor executor) {
        super(executor);
    }


    @Override
    public boolean addMsg(ChannelContext packet) {
        return false;
    }

    @Override
    public ConcurrentLinkedQueue<ChannelContext> getQueue() {
        return null;
    }

    @Override
    public void runTask() {
        if (msgQueue.isEmpty()) {
            return;
        }
        ChannelContext channelContext = null;
        while ((channelContext = msgQueue.poll()) != null) {

            try {
                boolean isNeedRemove = channelContext.closeMeta.isNeedRemove;
                String remark = channelContext.closeMeta.remark;
                Throwable throwable = channelContext.closeMeta.throwable;

                channelContext.channelStat.timeClosed = System.currentTimeMillis();


                try {
                    //					channelContext.traceClient(ChannelAction.UNCONNECT, null, null);

                    if (channelContext.isClosed && !isNeedRemove) {
                        log.info("{}, {}已经关闭，备注:{}，异常:{}", channelContext.config, channelContext, remark, throwable == null ? "无" : throwable.toString());
                        return;
                    }

                    if (channelContext.isRemoved) {
                        log.info("{}, {}已经删除，备注:{}，异常:{}", channelContext.config, channelContext, remark, throwable == null ? "无" : throwable.toString());
                        return;
                    }

                    //必须先取消任务再清空队列
                    channelContext.decodeRunnable.setCanceled(true);
                    channelContext.handleQueueRunnable.setCanceled(true);
                    channelContext.sendQueueRunnable.setCanceled(true);

                    channelContext.decodeRunnable.clearMsgQueue();
                    channelContext.handleQueueRunnable.clearMsgQueue();
                    channelContext.sendQueueRunnable.clearMsgQueue();

                    log.info("{}, {} 准备关闭连接, isNeedRemove:{}, {}", channelContext.config, channelContext, isNeedRemove, remark);

                    try {
                        if (isNeedRemove) {
                            MaintainUtils.remove(channelContext);
                        } else {
                            ClientConfig clientConfig = (ClientConfig) channelContext.config;
                            clientConfig.closeds.add(channelContext);
                            clientConfig.connecteds.remove(channelContext);
                            MaintainUtils.close(channelContext);
                        }

                        channelContext.setRemoved(isNeedRemove);

                        channelContext.channelStat.timeClosed = System.currentTimeMillis();
                        channelContext.setClosed(true);
                    } catch (Throwable e) {
                        log.error(e.toString(), e);
                    } finally {
                        if (!isNeedRemove && channelContext.isClosed && !channelContext.isServer()) //不删除且没有连接上，则加到重连队列中
                        {
                            ClientChannelContext clientChannelContext = (ClientChannelContext) channelContext;
                            ReconnConf.put(clientChannelContext);
                        }
                    }
                } catch (Throwable e) {
                    log.error(throwable.toString(), e);
                }

            } finally {
                channelContext.isWaitingClose = false;
            }
        }
    }

    /**
     * The msg queue.
     */
    private final ConcurrentLinkedQueue<ChannelContext> msgQueue = new ConcurrentLinkedQueue();
}
